/**
 * Copyright (C), 2001-2031, www.bosssof.com.cn
 * FileName: Client.java
 * Author: ckj
 * Date: 2024/7/20 下午9:11
 * Description:
 * 客户端
 * History:
 * Date          Author   Version  Desc
 * 2024-01-01    bosssoft  1.0.0   initialize this file
 */
package com.bosssoft.client;

import com.bosssoft.constants.FileExtensionConstant;
import com.bosssoft.factory.CustomThreadFactory;
import com.bosssoft.handle.ReceiveServerFileHandle;
import com.bosssoft.handle.ServerResponseHandle;
import com.bosssoft.issue.ReceiveServerFileIssue;
import com.bosssoft.issue.ServerResponseIssue;
import com.bosssoft.message.*;
import com.bosssoft.utils.AnalyzeJsonUtil;
import com.bosssoft.utils.AnalyzeXmlUtil;
import com.bosssoft.utils.ReaderUtil;
import com.bosssoft.utils.WriterUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.Socket;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import static com.bosssoft.constants.MessageTypeConstant.SERVER_RESPONSE_MESSAGE;
import static com.bosssoft.constants.MessageTypeConstant.THE_SERVER_SENDS_FILES_TO_THE_USER;


/**
 * @author ckj
 */
public class Client  {
    private boolean running = true;
    public static final String USER_FILE_PATH = "src/main/java/com/bosssoft/userfile/";
    private final ThreadPoolExecutor executorPool = new ThreadPoolExecutor(
            5, 10, 60, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(20), new CustomThreadFactory("发送消息线程")
    );
    private static final String SERVER_HOST = "127.0.0.1";
    private static final int SERVER_PORT = 8888;
    private static final int COMMAND_LENGTH = 3;
    private static final int SUCCESS_ANALYZE = 1;
    private static final Logger logger = LoggerFactory.getLogger(Client.class);
    private final String userName;

    /**
     * 
     * @author ckj
     * @date 2024/07/22 上午8:50
     * 初始化客户端用户名
     */
    public Client(String userId) {
        this.userName = userId;
    }

    public static void main(String[] args) {
        logger.info("开启客户端---");
        logger.info("请输入用户名---");
        Scanner sc = new Scanner(System.in);
        Client client = new Client(sc.nextLine());
        client.run();
    }

    /**
     * 
     * @author ckj
     * @date 2024/07/22 上午8:50
     * 客户端运行
     */
    public void run() {
        try (
                Socket socket = new Socket(SERVER_HOST, SERVER_PORT);
                PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);
                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))
        ) {
            register(writer);
            executorPool.execute(() -> {
                try {
                    handleResponse(reader);
                } catch (Exception e) {
                    logger.error("出错了");
                }
            });
            sendProcessing(writer);
        } catch (Exception e) {
            logger.error("出错了");
            System.exit(0);
        }
    }

    /**
     * 
     * @author ckj
     * 对输入的指令进行判断
     */
    public void sendProcessing(PrintWriter writer) {
        Scanner sc = new Scanner(System.in);
        String command;

        while (running) {
            logger.info("请输入指令");
            command = sc.nextLine();

            if ("exit".equals(command)) {
                executorPool.shutdown();
                running = false;
                System.exit(0);
            }

            if (command.startsWith("send")) {
                handleSendCommand(command, writer);
            } else if (command.startsWith("show")) {
                // 最多分成两个部分
                String[] parts = command.split("\\s+", 2);
                if (parts.length == 1){
                    handleShowCommand();
                }else {
                    String filename = parts[1];
                    handleShowFileCommand(filename);
                }

            }
        }
    }

    /**
     *
     * @author ckj
     * @date 2024/07/22 下午3:42
     * 解析文件（xml或者json）
     */
    private void handleShowFileCommand(String filename) {
        int res = 0;
        String needAnalyzeName = USER_FILE_PATH + userName + File.separator + filename;
        File file = new File(needAnalyzeName);
        if (!file.exists()) {
            logger.error("文件不存在");
            return;
        }
        if (filename.toLowerCase().endsWith(FileExtensionConstant.XML_EXTENSION)) {
            AnalyzeXmlUtil analyzeXmlUtil = AnalyzeXmlUtil.getInstance();
            res = analyzeXmlUtil.showXml(needAnalyzeName,this.userName);
        } else if (filename.toLowerCase().endsWith(FileExtensionConstant.JSON_EXTENSION)) {
            AnalyzeJsonUtil analyzeJsonUtil = AnalyzeJsonUtil.getInstance();
            res = analyzeJsonUtil.parseAndPrintJsonFromFile(needAnalyzeName,this.userName);
        }
        if(res == SUCCESS_ANALYZE){
            logger.info("解析成功，请在analyzefile文件夹下查找");
        } else {
            logger.info("解析失败");
        }
    }

    /**
     * 
     * @author ckj
     * @date 2024/07/22 上午8:59
     * 处理发送的指令
     */
    private void handleSendCommand(String command, PrintWriter writer) {
        String[] listOfParameters = command.split(" ");
        if (listOfParameters.length != COMMAND_LENGTH) {
            logger.info("参数错误");
            return;
        }

        String targetUserName = listOfParameters[1];
        String fileName = listOfParameters[2];
        File file = new File(USER_FILE_PATH + userName + File.separator + fileName);

        if (!file.exists()) {
            logger.info("文件不存在");
            return;
        }

        ArrayList<String> fileContentList = readFileContent(file);
        if (fileContentList.isEmpty()) {
            logger.info("文件读取错误");
            return;
        }

        SpecialPathFile specialPathFileMessage = new SpecialPathFile().sendMessageBuild(targetUserName, fileName, fileContentList);
        try {
            WriterUtil.writeToUser(writer, specialPathFileMessage.convertFromTransferableDataList());
        } catch (Exception e) {
            logger.error("发送指令错误");
        }
    }

    /**
     * 
     * @author ckj
     * @date 2024/07/22 上午9:00
     * 通过逐行读取指定文件的内容
     * @return java.util.ArrayList<java.lang.String> 
     */
    private ArrayList<String> readFileContent(File file) {
        ArrayList<String> fileContentList = new ArrayList<>();
        try (BufferedReader fileReader = new BufferedReader(new InputStreamReader(Files.newInputStream(file.toPath())))) {
            String line;
            while ((line = fileReader.readLine()) != null) {
                fileContentList.add(line);
            }
        } catch (IOException e) {
            return new ArrayList<>();
        }
        return fileContentList;
    }

    /**
     * 
     * @author ckj
     * @date 2024/07/22 上午8:55
     * 处理show指令
     */
    private void handleShowCommand() {

        File file = new File(USER_FILE_PATH + userName);
        logger.info(file.getPath());
        if (!file.exists()) {
            boolean success = file.mkdir();
            if (success) {
                logger.info("成功创建文件夹");
            } else {
                logger.info("创建文件夹失败");
            }
            return;
        }

        String[] list = file.list();
        if (list == null || list.length == 0) {
            logger.info("没有文件");
            return;
        }

        for (String s : list) {
            logger.info(s);
        }
    }


    /**
     * 
     * @author ckj
     * @date 2024/07/22 上午8:55
     * 从服务器读取消息，并根据消息的类型执行相应的处理逻辑，以确保客户端能够正确处理和响应服务器发送的各种消息
     */
    public void handleResponse(BufferedReader reader) throws Exception {
        while ( running ){
            if("Start".equals(reader.readLine())){
                int type = Integer.parseInt(ReaderUtil.readLineWithAes(reader));
                if(type == SERVER_RESPONSE_MESSAGE ){
                    BaseMessage message = new ServerMessage().parse(reader, type);
                    ServerResponseIssue serverResponseIssue = new ServerResponseIssue(message);
                    new ServerResponseHandle().handle(serverResponseIssue);
                }
                if (type==THE_SERVER_SENDS_FILES_TO_THE_USER){
                    BaseMessage message = new ReceiveServerFile().parse(reader, type);
                    ReceiveServerFileIssue receiveServerFileIssue = new ReceiveServerFileIssue(userName,message);
                    new ReceiveServerFileHandle().handle(receiveServerFileIssue);
                }
            }
        }
    }

    /**
     * 
     * @author ckj
     * @date 2024/07/22 上午8:53
     * 注册用户账户
     */
    private void register(PrintWriter writer) throws Exception {
        String msg = "正在注册 " + userName + " 账户";
        logger.info(msg);
        RegisterMessage registeredMessage = new RegisterMessage().sendMessageBuild(userName);
        WriterUtil.writeToUser(writer,registeredMessage.convertFromTransferableDataList());
    }
}
